/*
 * Copyright (C) 2024 HiHope Open Source Organization.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import createOrGet from '../utils/SingleInstanceHelper';
import { Log } from '../utils/Log';
import { notificationManager } from '@kit.NotificationKit';
import wantAgent from '@ohos.app.ability.wantAgent';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG: string = 'NotificationManager'

export interface NormalNotificationArgs {
  title: string,
  text: string,
  additionalText?: string,
  wantAgent: object
}

export class NotificationManager {
  init() {
    let isNotificationEnabled: boolean = notificationManager.isNotificationEnabledSync()
    Log.debug(TAG, `init, isNotificationEnabled: ${isNotificationEnabled}`)
    if (!isNotificationEnabled) {
      notificationManager.requestEnableNotification().then(() => {
        Log.info(TAG, 'requestEnableNotification success')
        this.createNotificationSlots()
      }).catch((error: BusinessError) => {
        Log.error(TAG, `requestEnableNotification failed: ${error}, ${JSON.stringify(error)}`)
      })
    } else {
      this.createNotificationSlots()
    }
  }

  createNotificationSlots() {
    // 传输进度通知用slot,live类型无需cancel就可刷新同id的notification, 避免更新进度条时通知列表闪烁
    this.createNotificationSlot('LiveNotifications', notificationManager.SlotType.LIVE_VIEW,
      notificationManager.SlotLevel.LEVEL_DEFAULT);
    // 普通通知用slot, 无横幅通知, 界面处于前台时使用
    this.createNotificationSlot('NoBannerNotifications', notificationManager.SlotType.SERVICE_INFORMATION,
      notificationManager.SlotLevel.LEVEL_DEFAULT);
    // 普通通知用slot, 有横幅通知, 界面处于后台时使用
    this.createNotificationSlot('BannerNotifications', notificationManager.SlotType.SOCIAL_COMMUNICATION,
      notificationManager.SlotLevel.LEVEL_HIGH);
  }

  createNotificationSlot(slotName: string, slotType: notificationManager.SlotType,
    slotLevel: notificationManager.SlotLevel) {
    notificationManager.getSlot(slotType)
      .then((slot: notificationManager.NotificationSlot) => {
        Log.info(TAG, `get ${slotType} Slot success: ${JSON.stringify(slot)}`);
        if (!slot) {
          notificationManager.addSlot({
            desc: slotName,
            level: slotLevel,
            notificationType: slotType,
            badgeFlag: false,
            vibrationEnabled: false
          }).then(() => {
            Log.info(TAG, `create ${slotType} Slot success`);
          }).catch((error: BusinessError) => {
            Log.error(TAG, `create ${slotType} Slot failed: ${error}, ${JSON.stringify(error)}`);
          })
        }
      }).catch((error: BusinessError) => {
      Log.error(TAG, `get ${slotType} Slot failed: ${error}, ${JSON.stringify(error)}`);
    });
  }

  async publishLiveNotification(args: NormalNotificationArgs) {
    Log.info(TAG, `publishLiveNotification in, ${JSON.stringify(args)}`)

    let notificationRequest: notificationManager.NotificationRequest = {
      id: 0,
      content: {
        notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
        normal: { title: args.title, text: args.text },
      },
      notificationSlotType:notificationManager.SlotType.LIVE_VIEW,
      wantAgent: args.wantAgent
    }
    try {
      await notificationManager.publish(notificationRequest)
      Log.info(TAG, 'publish success')
    } catch (error) {
      Log.error(TAG, `publish failed: ${error}, ${JSON.stringify(error)}`)
    }
  }

  async publishBannerNotification(args: NormalNotificationArgs, needShowBanner: boolean) {
    Log.info(TAG, `publishBannerNotification in, ${JSON.stringify(args)}`)
    await this.cancelNotification();

    let notificationRequest: notificationManager.NotificationRequest = {
      id: 0,
      content: {
        notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
        normal: { title: args.title, text: args.text || '' },
      },
      notificationSlotType: needShowBanner ? notificationManager.SlotType.SOCIAL_COMMUNICATION :
      notificationManager.SlotType.SERVICE_INFORMATION,
      wantAgent: args.wantAgent
    }
    try {
      await notificationManager.publish(notificationRequest)
      Log.info(TAG, 'publish success')
    } catch (error) {
      Log.error(TAG, `publish failed: ${error}, ${JSON.stringify(error)}`)
    }
  }

  async cancelNotification() {
    Log.info(TAG, `cancelNotification in`);
    try {
      await notificationManager.cancel(0);
      Log.info(TAG, 'cancel success');
    } catch (error) {
      Log.error(TAG, `cancel failed: ${error}, ${JSON.stringify(error)}`);
    }
  }

  getNotificationId(deviceId: string): number {
    return Number.parseInt(deviceId.length > 8 ? deviceId.substring(deviceId.length - 8) : deviceId, 16)
  }
}

const sNotificationManager: NotificationManager = createOrGet(NotificationManager, 'NotificationManager')

export default sNotificationManager